// MIT License
// 开源地址：https://gitee.com/co1024/AbcMvc
// Copyright (c) 2021-2023 1024
// Abc.Mvc=Furion+EF+SqlSugar+Pear layui admin.

namespace Abc.Utils;

/// <summary>
///  DateTime 扩展
/// </summary>
public static class DateTimeExtension
{
    /// <summary>
    /// 返回格式为(yyyy-MM-dd HH:mm:ss)的时间字符串
    /// </summary>
    /// <param name="dt"></param>
    /// <returns></returns>
    public static string ToStringLongDate(this DateTime dt)
    {
        return dt.ToString("yyyy-MM-dd HH:mm:ss");
    }

    /// <summary>
    /// 返回格式为(yyyy-MM-dd HH:mm:ss)的时间字符串
    /// </summary>
    /// <param name="dt"></param>
    /// <returns></returns>
    public static string ToStringLongDate(this DateTime? dt)
    {
        return dt?.ToString("yyyy-MM-dd HH:mm:ss") ?? "";
    }

    /// <summary>
    /// 返回格式为(yyyy-MM-dd)的时间字符串
    /// </summary>
    /// <param name="dt"></param>
    /// <returns></returns>
    public static string ToStringDate(this DateTime dt)
    {
        return dt.ToString("yyyy-MM-dd");
    }

    /// <summary>
    /// 返回格式为(yyyy-MM-dd)的时间字符串
    /// </summary>
    /// <param name="dt"></param>
    /// <returns></returns>
    public static string ToStringDate(this DateTime? dt)
    {
        return dt?.ToString("yyyy-MM-dd") ?? "";
    }

    /// <summary>
    /// 返回格式为(yyyy-MM-dd HH:mm:ss)的时间字符串
    /// </summary>
    /// <param name="dt"></param>
    /// <returns></returns>
    public static string ToStringLongDate(this DateTimeOffset dt)
    {
        return dt.ToString("yyyy-MM-dd HH:mm:ss");
    }

    /// <summary>
    /// 返回格式为(yyyy-MM-dd HH:mm:ss)的时间字符串
    /// </summary>
    /// <param name="dt"></param>
    /// <returns></returns>
    public static string ToStringLongDate(this DateTimeOffset? dt)
    {
        return dt?.ToString("yyyy-MM-dd HH:mm:ss") ?? "";
    }

    /// <summary>
    /// 返回格式为(yyyy-MM-dd)的时间字符串
    /// </summary>
    /// <param name="dt"></param>
    /// <returns></returns>
    public static string ToStringDate(this DateTimeOffset dt)
    {
        return dt.ToString("yyyy-MM-dd");
    }

    /// <summary>
    /// 返回格式为(yyyy-MM-dd)的时间字符串
    /// </summary>
    /// <param name="dt"></param>
    /// <returns></returns>
    public static string ToStringDate(this DateTimeOffset? dt)
    {
        return dt?.ToString("yyyy-MM-dd") ?? "";
    }
    #region 时间戳
    /// <summary>
    /// 获取时间戳，默认10位
    /// 10位：精确到秒
    /// 13位：精确到毫秒
    /// </summary>
    /// <param name="milliseconds">精确到毫秒</param>
    /// <returns></returns>
    public static long ToTimeStamp(this DateTime dateTime, bool milliseconds = false)
    {
        var ts = dateTime - new DateTime(1970, 1, 1, 0, 0, 0, 0);
        //是否精确到毫秒
        if (milliseconds)
        {
            //精确到毫秒
            return Convert.ToInt64(ts.TotalMilliseconds);

        }
        else
        {
            //精确到秒
            return Convert.ToInt64(ts.TotalSeconds);
        }

    }
    /// <summary>
    /// 获取时间戳，默认10位
    /// 10位：精确到秒
    /// 13位：精确到毫秒
    /// <param name="milliseconds">精确到毫秒</param>
    /// <returns></returns>
    public static long ToTimeStamp(this DateTimeOffset dateTime, bool milliseconds = false)
    {
        //var ts = dateTime.UtcDateTime - new DateTime(1970, 1, 1, 0, 0, 0, 0);
        //是否精确到毫秒
        if (milliseconds)
        {
            //精确到毫秒
            //return Convert.ToInt64(ts.TotalMilliseconds);
            return dateTime.ToUnixTimeMilliseconds();
        }
        else
        {
            //精确到秒
            //return Convert.ToInt64(ts.TotalSeconds);
            return dateTime.ToUnixTimeSeconds();
        }
    }

    /// <summary>
    /// 获取时间戳，默认10位
    /// </summary>
    /// 10位：精确到秒
    /// 13位：精确到毫秒
    /// <param name="accurateToMilliseconds">精确到毫秒</param>
    /// <returns></returns>
    public static long GetTimeStamp(DateTime dateTime, bool milliseconds = false)
    {
        return dateTime.ToTimeStamp(milliseconds);
    }

    /// <summary>
    /// 获取时间戳，默认10位
    /// </summary>
    /// 10位：精确到秒
    /// 13位：精确到毫秒
    /// <param name="milliseconds">精确到毫秒</param>
    /// <returns></returns>
    public static long GetTimeStamp(DateTimeOffset dateTime, bool milliseconds = false)
    {
        return dateTime.ToTimeStamp(milliseconds);
    }

    /// <summary>
    /// 将时间戳转换为日期类型，并格式化
    /// 支持10、13位时间戳
    /// </summary>
    /// <param name="timeStamp"></param>
    /// <param name="format">时间格式：默认：yyyy-MM-dd HH:mm:ss</param>
    /// <returns>默认：yyyy-MM-dd HH:mm:ss 的字符串</returns>
    private static string TimeStampToDateTimeString(this string timeStamp, string format = "yyyy-MM-dd HH:mm:ss")
    {
        return timeStamp.ToDateTime().ToString(format);
    }

    /// <summary>
    ///  时间戳转为+00:00时区 日期格式  yyyy/MM/dd HH:mm:ss
    /// </summary>
    /// <param name="timeStamp"></param>
    /// <returns></returns>
    public static DateTime GetDateTime(string timeStamp)
    {
        long lTime = long.Parse(timeStamp);
        if (timeStamp.Length == 10)
        {
            //秒的时间戳
            return DateTimeOffset.FromUnixTimeSeconds(lTime).DateTime;
        }
        else
        {
            //毫秒的时间戳
            return DateTimeOffset.FromUnixTimeMilliseconds(lTime).DateTime;
        }
    }

    /// <summary>
    /// 时间戳转换成时间
    /// </summary>
    /// 10位：精确到秒
    /// 13位：精确到毫秒
    /// <param name="milliseconds">精确到毫秒</param>
    /// <returns></returns>
    public static DateTime ToDateTime(this string timestamp)
    {
        return timestamp.ToLong().ToDateTime();
    }

    /// <summary>
    /// 时间戳转换成时间
    /// </summary>
    /// <returns></returns>
    public static DateTime ToDateTime(this long timestamp)
    {
        DateTime start = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
        DateTime startTime = TimeZoneInfo.ConvertTime(start, TimeZoneInfo.Local);
        if (timestamp.ToString().Length == 13)
        {
            //毫秒级时间戳
            startTime.AddMilliseconds(timestamp);
        }
        else
        {
            //根据时间戳类型就行转换
            //例：秒级时间戳
            startTime.AddSeconds(timestamp);
        }

        return startTime;
    }

    /// <summary>
    /// 时间戳转换成时间
    /// </summary>
    /// <returns></returns>
    public static DateTimeOffset ToDateTimeOffset(this string timestamp)
    {
        return timestamp.ToLong().ToDateTimeOffset();
    }

    /// <summary>
    /// 时间戳转换成时间
    /// </summary>
    /// <returns></returns>
    public static DateTimeOffset ToDateTimeOffset(this long timestamp)
    {
        var dt = timestamp.ToDateTime();

        dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
        DateTimeOffset utcTime2 = dt;

        return utcTime2;
    }

    ///// <summary>
    ///// 计算两个时间戳的间隔
    ///// </summary>
    /////<param name="timeStamp1"></param>
    /////<param name="timeStamp2"></param>
    ///// <returns></returns>
    //public static TimeSpan GetTwoTimeSpan(this string timeStamp1, string timeStamp2)
    //{
    //    //获取时间戳，并将其转换为DateTimeOffset
    //    //var UninTimeStamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
    //    long lTime1 = long.Parse(timeStamp1);
    //    long lTime2 = long.Parse(timeStamp2);
    //    var DateTimeUnix1 = DateTimeOffset.FromUnixTimeSeconds(lTime1);
    //    var DateTimeUnix2 = DateTimeOffset.FromUnixTimeSeconds(lTime2);
    //    //计算两个时间间隔
    //    TimeSpan timeSpan = new TimeSpan(DateTimeUnix2.Ticks - DateTimeUnix1.Ticks);
    //    return timeSpan;
    //}

    #endregion


    #region ToDayEndTime DateTimeOffset

    /// <summary>
    /// 一天的结束时间  23:59:59
    /// </summary>
    /// <param name="dt"></param>
    /// <returns></returns>
    public static DateTimeOffset ToDayEndTime(this DateTimeOffset dt)
    {
        return DateTimeOffset.Parse($"{dt:yyyy-MM-dd} 23:59:59");
    }

    /// <summary>
    /// 一天的结束时间  23:59:59
    /// </summary>
    /// <param name="dt"></param>
    /// <returns></returns>
    public static DateTimeOffset ToDayEndTime(this DateTimeOffset? dt)
    {
        return DateTimeOffset.Parse($"{dt:yyyy-MM-dd} 23:59:59");
    }

    /// <summary>
    /// 一天的开始时间  00:00:00
    /// </summary>
    /// <param name="dt"></param>
    /// <returns></returns>
    public static DateTimeOffset ToDayStartTime(this DateTimeOffset dt)
    {
        return DateTimeOffset.Parse($"{dt:yyyy-MM-dd} 00:00:00");
    }

    /// <summary>
    /// 一天的开始时间  00:00:00
    /// </summary>
    /// <param name="dt"></param>
    /// <returns></returns>
    public static DateTimeOffset ToDayStartTime(this DateTimeOffset? dt)
    {
        return DateTimeOffset.Parse($"{dt:yyyy-MM-dd} 00:00:00");
    }

    #endregion ToDayEndTime DateTimeOffset

    #region ToDayEndTime DateTime

    /// <summary>
    /// 一天的结束时间  23:59:59
    /// </summary>
    /// <param name="dt"></param>
    /// <returns></returns>
    public static DateTime ToDayEndTime(this DateTime dt)
    {
        return Convert.ToDateTime($"{dt:yyyy-MM-dd} 23:59:59");
    }

    /// <summary>
    /// 一天的结束时间  23:59:59
    /// </summary>
    /// <param name="dt"></param>
    /// <returns></returns>
    public static DateTime ToDayEndTime(this DateTime? dt)
    {
        return Convert.ToDateTime($"{dt:yyyy-MM-dd} 23:59:59");
    }

    /// <summary>
    /// 一天的开始时间  00:00:00
    /// </summary>
    /// <param name="dt"></param>
    /// <returns></returns>
    public static DateTime ToDayStartTime(this DateTime dt)
    {
        return Convert.ToDateTime($"{dt:yyyy-MM-dd} 00:00:00");
    }

    /// <summary>
    /// 一天的开始时间  00:00:00
    /// </summary>
    /// <param name="dt"></param>
    /// <returns></returns>
    public static DateTime ToDayStartTime(this DateTime? dt)
    {
        return Convert.ToDateTime($"{dt:yyyy-MM-dd} 00:00:00");
    }

    #endregion ToDayEndTime DateTime
}